package com.cardinalscientific.apps.speedwatcher;

//import java.text.SimpleDateFormat;
//import java.util.Date;
import java.util.Locale;

import com.google.ads.AdRequest;
import com.google.ads.AdView;

import kankan.wheel.widget.OnWheelClickedListener;
import kankan.wheel.widget.OnWheelScrollListener;
import kankan.wheel.widget.WheelView;
import kankan.wheel.widget.adapters.NumericWheelAdapter;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;

public class HomeActivity extends Activity 
						  implements OnInitListener , 
						  			 LocationListener, 
						  			 OnWheelClickedListener,
						  			 OnWheelScrollListener {
						  			 

	//private final static String TAG = "HomeActivity";
	private final static String MPH = "miles per hour";
	private final static String KPH = "kilometers per hour";
	private final static int TTS_DATA_CHECK_CODE = 0;
	//private final static SimpleDateFormat mTimeStampFormatter = new SimpleDateFormat("hh:mm:ss");
	
	private SharedPreferences mSharedPref;
	private Resources mResources;
	
	private RelativeLayout mRootLayout;
	private WheelView mTenthPlace;
	private WheelView mUnitPlace;
	private TextView mCurrentSpeedView;
	private TextView mPostedSpeedView;
	private EditText mEventLog;
	
	private Intent mSettingIntent;
	private LocationManager mLocationManager;
	private TextToSpeech mTTS;
	private Vibrator mVibrator;
	private Handler mTTSHandler;
	private Runnable mTTSTask;
	
	private int mPostedSpeed = 0;		//Speed Target	
	private int mCurrentSpeed = 0;		//Speed Actual
	//private int mPrevCurrentSpeed = 0; 	//Previous Speed Actual
	private long[] mVibratePattern;
	
	private String mOutputDevice;		//Contains output device
	
	private int mGreenColor;
	private int mWhiteColor;
	private int mRedColor;
	private AnimatorSet mAnimationSet;
	private ValueAnimator mGreenAnimation;
	private ValueAnimator mRedAnimation;
	
	private class SpeedNumericAdapter extends NumericWheelAdapter {
  
        public SpeedNumericAdapter(Context context, int minValue, int maxValue, int current) {
            super(context, minValue, maxValue);
            setTextSize(32);
        }
        
        @Override
        protected void configureTextView(TextView view) {
            super.configureTextView(view);
            view.setTypeface(Typeface.DEFAULT_BOLD);
        }
	}
	
	/**************************************************************************
	 *	Activity lifecycle callback methods
	 *************************************************************************/
	 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.home_activity);
		
		mRootLayout = (RelativeLayout)this.findViewById(R.id.root);
		
		AdView adView = (AdView)this.findViewById(R.id.adView);
	    adView.loadAd(new AdRequest());
	   
		mSettingIntent = new Intent(this, SettingsActivity.class);
		mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
		mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
		checkUserData();
		mVibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
		mSharedPref= PreferenceManager.getDefaultSharedPreferences(this);
		mResources = getResources();
		mTTSHandler = new Handler();
		
		mTenthPlace = (WheelView) this.findViewById(R.id.tenth_place);
		mTenthPlace.setViewAdapter(new SpeedNumericAdapter(this, 0, 15, 4));
		mTenthPlace.setCurrentItem(5);
		mTenthPlace.addClickingListener(this);
		mTenthPlace.addScrollingListener(this);
		
		mUnitPlace = (WheelView) this.findViewById(R.id.unit_place);
		mUnitPlace.setViewAdapter(new SpeedNumericAdapter(this, 0, 9, 4));
		mUnitPlace.setCurrentItem(5);
		mUnitPlace.addClickingListener(this);
		mUnitPlace.addScrollingListener(this);
		
		mCurrentSpeedView = (TextView) this.findViewById(R.id.tvCurrentSpeed);
		mPostedSpeedView = (TextView)this.findViewById(R.id.tvPostedSpeed);
		
		//mEventLog = (EditText) this.findViewById(R.id.etLog);
		//mEventLog.setFocusable(false); 
		//mEventLog.setClickable(false);
		
		mTTSTask = new Runnable() {

			@Override
			public void run() {
				
				int threshold = mSharedPref.getInt(mResources.getString(R.string.pref_speed_threshold_key), 5);
				int speed_limit = mPostedSpeed + threshold;
				//int speed_slop = mCurrentSpeed - mPrevCurrentSpeed; //Indicates speed in increasing
				mOutputDevice = mSharedPref.getString(mResources.getString(R.string.pref_devices_key), "0");
			
				//if(mCurrentSpeed > speed_limit && speed_slop > 0) {
				if(mCurrentSpeed > speed_limit) {
					
					int above = mCurrentSpeed - mPostedSpeed;
					if(mOutputDevice.equals("0")) {
						speekSpeedLimit(above);
					}else {
						vibrateSpeedLimit(above);
					}
					
					playRedAnim();
					//mEventLog.append(getTimestamp() + ": " + Integer.toString(above) + "\n");
					
				} else {
					
					playGreenAnim();
					//mEventLog.append(getTimestamp() + ": You are good!\n");
				}
				
				int alertRate = mSharedPref.getInt(mResources.getString(R.string.pref_alert_freq_key), 10);
				mTTSHandler.postDelayed(this, alertRate * 1000);
			}
		};
		
		mVibratePattern = new long[]{0, 500, 500, 500, 500, 500, 500};
		
		setupAnimation();
		playGreenAnim();
	
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		mTTSHandler.removeCallbacks(mTTSTask);
		
		int alertRate = mSharedPref.getInt(mResources.getString(R.string.pref_alert_freq_key), 10);
		mTTSHandler.postDelayed(mTTSTask, alertRate * 1000);
		
		mPostedSpeed = calculatePostedSpeed(mTenthPlace.getCurrentItem(), mUnitPlace.getCurrentItem());
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		mTTSHandler.removeCallbacks(mTTSTask);
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.home, menu);
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item){
		switch (item.getItemId()){
			case R.id.action_settings:
				this.startActivity(mSettingIntent);
				return true;
			default:
				return super.onOptionsItemSelected(item);
		}
	}
	
	public void onSpeakClicked(View v) {
		mEventLog.setText("");
	}
	
	/**************************************************************************
	 *	Thumbwheel callback methods
	 *************************************************************************/
	
	@Override
	public void onScrollingStarted(WheelView wheel) {}
	
	@Override
	public void onScrollingFinished(WheelView wheel) {
		mPostedSpeed = calculatePostedSpeed(mTenthPlace.getCurrentItem(), mUnitPlace.getCurrentItem());
	}

	@Override
	public void onItemClicked(WheelView wheel, int itemIndex) {
		wheel.setCurrentItem(itemIndex, true);
        mPostedSpeed = calculatePostedSpeed(mTenthPlace.getCurrentItem(), mUnitPlace.getCurrentItem());
	}

	/**************************************************************************
	 *	Text To Speech Methods 
	 *************************************************************************/
	
	private void speekSpeedLimit(int above) {
		String speak;
		if(getCurrentSpeedUnit().equals("mph")){
			speak = String.format(mResources.getString(R.string.speek_speed_limit), above, MPH);
		} else {
			speak = String.format(mResources.getString(R.string.speek_speed_limit), above, KPH);
		}
		mTTS.speak(speak, TextToSpeech.QUEUE_FLUSH, null);
	}
	
	@Override
	public void onInit(int status) {
		 if (status == TextToSpeech.SUCCESS) {
			 if(mTTS.isLanguageAvailable(Locale.US) == TextToSpeech.LANG_AVAILABLE)
				 mTTS.setLanguage(Locale.US);
		 } else if (status == TextToSpeech.ERROR) {
			    Toast.makeText(this, "Sorry! Text To Speech failed...", Toast.LENGTH_LONG).show();
		 }
	}

	private void checkUserData() {
		Intent checkTTSIntent = new Intent();
		checkTTSIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
		startActivityForResult(checkTTSIntent, TTS_DATA_CHECK_CODE);
	}
	
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == TTS_DATA_CHECK_CODE) {
			if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
				mTTS = new TextToSpeech(this, this);
			} else {
				Intent installTTSIntent = new Intent();
	            installTTSIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
	            startActivity(installTTSIntent);
			}
		}
	}

	/**************************************************************************
	 *	Location interface 
	 *************************************************************************/
	
	@Override
	public void onLocationChanged(Location location) {
		String display;
		if(getCurrentSpeedUnit().equals("mph")){ //mph
			mCurrentSpeed = Math.round((float)(2.236936) * location.getSpeed());
			display = String.format(mResources.getString(R.string.current_speed), 
					   mCurrentSpeed,
					   "mph");
		}else{ //kmh
			mCurrentSpeed = Math.round((float)(3.6) * location.getSpeed());
			display = String.format(mResources.getString(R.string.current_speed), 
					   mCurrentSpeed,
					   "kmh");
		}
		mCurrentSpeedView.setText(display);
		//mPrevCurrentSpeed = mCurrentSpeed;
	}

	@Override
	public void onProviderDisabled(String provider) {}

	@Override
	public void onProviderEnabled(String provider) {}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {}
	
	/**************************************************************************
	 *	Other Private methods 
	 *************************************************************************/
	
	private void vibrateSpeedLimit(int above) {
		mVibrator.vibrate(mVibratePattern, -1);
	}
	
	private int calculatePostedSpeed(int tenth, int unit) {
		int speed = 10 * (tenth) + unit;
		String display = String.format(this.getResources().getString(R.string.posted_speed), speed, getCurrentSpeedUnit());
		mPostedSpeedView.setText(display);
		return speed;
	}
	
	private String getCurrentSpeedUnit() {
		String speedUnit = mSharedPref.getString(mResources.getString(R.string.pref_speed_unit_key), "0");
		if(speedUnit.equals("0")) {
			return "mph";
		}else{
			return "kmh";
		}
	}
	
	/*private String getTimestamp() {
		Date d = new Date();
		return mTimeStampFormatter.format(d);
	}*/
	
	private void playGreenAnim() {
		mGreenAnimation = ObjectAnimator.ofInt(mRootLayout, "backgroundColor", mWhiteColor, mGreenColor);
		mGreenAnimation.setDuration(2200);
		mGreenAnimation.setEvaluator(new ArgbEvaluator());
		mGreenAnimation.setRepeatCount(ValueAnimator.INFINITE);
		mGreenAnimation.setRepeatMode(ValueAnimator.REVERSE);
		
		mAnimationSet.play(mGreenAnimation);
		mAnimationSet.start();
	}
	
	private void playRedAnim() {
		mRedAnimation = ObjectAnimator.ofInt(mRootLayout, "backgroundColor", mWhiteColor, mRedColor);
		mRedAnimation.setDuration(2200);
		mRedAnimation.setEvaluator(new ArgbEvaluator());
		mRedAnimation.setRepeatCount(ValueAnimator.INFINITE);
		mRedAnimation.setRepeatMode(ValueAnimator.REVERSE);
		
		mAnimationSet.play(mRedAnimation);
		mAnimationSet.start();
	}	
	
	private void setupAnimation() {
		mAnimationSet = new AnimatorSet();
		mGreenColor = this.getResources().getColor(R.color.PaleGreen);
		mWhiteColor = this.getResources().getColor(R.color.white);
		mRedColor = this.getResources().getColor(R.color.OrangeRed);
	}
}
